package com.ly.mpayment.core.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.EnumMap;
import java.util.Hashtable;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.log4j.Logger;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QRcodeUtil {
	private static final int BLACK = 0xFF000000;
	private static final int WHITE = 0xFFFFFFFF;
	private static final int margin = 0;
	private static final int LogoPart = 4;
	static Logger logger = Logger.getLogger(QRcodeUtil.class);
	/**
	 * 生成二维码矩阵信息
	 *
	 * @param content
	 *            二维码图片内容
	 * @param width
	 *            二维码图片宽度
	 * @param height
	 *            二维码图片高度
	 */
	public static BitMatrix setBitMatrix(String content, int width, int height) {
		Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级
		hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小
		BitMatrix bitMatrix = null;
		try {
			bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
		} catch (WriterException e) {
			e.printStackTrace();
		}
		return bitMatrix;
	}

	/**
	 * 将二维码图片输出
	 *
	 * @param matrix
	 *            二维码矩阵信息
	 * @param format
	 *            图片格式
	 * @param outStream
	 *            输出流
	 * @param logoPath
	 *            logo图片路径
	 */
	public static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, String logoPath)
			throws IOException {
		BufferedImage image = toBufferedImage(matrix);
		// 加入LOGO水印效果
		if (!StringUtils.isBlank(logoPath)) {
			image = addLogo(image, logoPath);
		}
		ImageIO.write(image, format, outStream);
	}

	/**
	 * 生成二维码图片
	 *
	 * @param matrix
	 *            二维码矩阵信息
	 */
	public static BufferedImage toBufferedImage(BitMatrix matrix) {
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
			}
		}
		return image;
	}

	/**
	 * 在二维码图片中添加logo图片
	 *
	 * @param image
	 *            二维码图片
	 * @param logoPath
	 *            logo图片路径
	 */
	public static BufferedImage addLogo(BufferedImage image, String logoPath) throws IOException {
		Graphics2D g = image.createGraphics();
		BufferedImage logoImage = ImageIO.read(new File(logoPath));
		// 计算logo图片大小,可适应长方形图片,根据较短边生成正方形
		int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart;
		int height = width;
		// 计算logo图片放置位置
		int x = (image.getWidth() - width) / 2;
		int y = (image.getHeight() - height) / 2;
		// 在二维码图片上绘制logo图片
		g.drawImage(logoImage, x, y, width, height, null);
		// 绘制logo边框,可选
		// g.drawRoundRect(x, y, logoImage.getWidth(), logoImage.getHeight(),
		// 10, 10);
		g.setStroke(new BasicStroke(2)); // 画笔粗细
		g.setColor(Color.WHITE); // 边框颜色
		g.drawRect(x, y, width, height); // 矩形边框
		logoImage.flush();
		g.dispose();
		return image;
	}

	/**
	 * 为图片添加文字
	 *
	 * @param pressText
	 *            文字
	 * @param newImage
	 *            带文字的图片
	 * @param targetImage
	 *            需要添加文字的图片
	 * @param fontStyle
	 *            字体风格
	 * @param color
	 *            字体颜色
	 * @param fontSize
	 *            字体大小
	 * @param width
	 *            图片宽度
	 * @param height
	 *            图片高度
	 */
	public static void pressText(String pressText, String newImage, String targetImage, int fontStyle, Color color,
			int fontSize, int width, int height) {
		// 计算文字开始的位置
		// x开始的位置：（图片宽度-字体大小*字的个数）/2
		int startX = (width - (fontSize * pressText.length())) / 2;
		// y开始的位置：图片高度-（图片高度-图片宽度）/2
		int startY = height - (height - width) / 2 + fontSize;
		try {
			File file = new File(targetImage);
			BufferedImage src = ImageIO.read(file);
			int imageW = src.getWidth(null);
			int imageH = src.getHeight(null);
			BufferedImage image = new BufferedImage(imageW, imageH, BufferedImage.TYPE_INT_RGB);
			Graphics g = image.createGraphics();
			g.drawImage(src, 0, 0, imageW, imageH, null);
			g.setColor(color);
			g.setFont(new Font(null,fontStyle, fontSize));
			g.drawString(pressText, startX, startY);
			g.dispose();
			FileOutputStream out = new FileOutputStream(newImage);
			ImageIO.write(image, "png", out);
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
//		String content = "http://www.baidu.com";
//		String logoPath = "";
//		String format = "jpg";
//		int width = 180;
//		int height = 220;
//		BitMatrix bitMatrix = setBitMatrix(content, width, height);
//		// 可通过输出流输出到页面,也可直接保存到文件
//		OutputStream outStream = null;
//		String path = "f:/qr" + new Date().getTime() + ".png";
//		try {
//			outStream = new FileOutputStream(new File(path));
//			writeToFile(bitMatrix, format, outStream, logoPath);
//			outStream.close();
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		// 添加文字效果
//		int fontSize = 12; // 字体大小
//		int fontStyle = 1; // 字体风格
//		String text = "测试二维码";
//		String withTextPath = "f:/text" + new Date().getTime() + ".png";
//		pressText(text, withTextPath, path, fontStyle, Color.BLUE, fontSize, width, height);
		System.out.println(decodeQR("C:\\Users\\long\\Desktop\\1562164059700.jpg"));
	}

	/**
	 * 解析二维码图片
	 *
	 * @param filePath
	 *            图片路径
	 */
	public static String decodeQR(String filePath) {
		if ("".equalsIgnoreCase(filePath) && filePath.length() == 0) {
			return "二维码图片不存在!";
		}
		String content = "";
		EnumMap<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
		hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
		hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
		hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
		try {
			BufferedImage image = ImageIO.read(new FileInputStream(filePath));
			LuminanceSource source = new BufferedImageLuminanceSource(image);
			Binarizer binarizer = new HybridBinarizer(source);
			BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
			MultiFormatReader reader = new MultiFormatReader();
			Result result = reader.decode(binaryBitmap, hints);
			content = result.getText();
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return content;
	}

	/**
	 * 获取支付二维码
	 * @param url
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public static String getQrcode(String url,Map<String, String> headers,String type) {
		File filepicF = null;
		DefaultHttpClient client = new SystemDefaultHttpClient();
		try {
			// 发送get请求
			HttpGet request = new HttpGet(url);
			if(headers != null){
				for(String key : headers.keySet()){
					request.setHeader(key, headers.get(key));
				}
			}
			HttpResponse response = client.execute(request);
			/** 请求发送成功，并得到响应 **/
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

				String picName = CookieRedis.get("exportPath");
				File filepic = new File(picName);
				if (!filepic.exists()){
					filepic.mkdir();
				}
				filepicF = new File(picName + new Date().getTime() + type);

				InputStream inputStream = response.getEntity().getContent();
				OutputStream outStream = new FileOutputStream(filepicF);
				IOUtils.copy(inputStream, outStream);
				outStream.close();
				client.getConnectionManager().shutdown();
				return QRcodeUtil.decodeQR(filepicF.getAbsolutePath());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			client.getConnectionManager().shutdown();
		}
		return null;
	}
}
